
#include "CORD1CData.h"

#include <assert.h>

#include <cmath>

#include "DataStructure/Common/Constant.h"

using SG::Algebra::Point;
using SG::Algebra::Vector3D;
using SG::DataStructure::Common::PI;
using SG::DataStructure::Common::Real;
using SG::DataStructure::FEM::CylinderCoord;

/** @brief 单元的每个节点定义在世界坐标系或者 节点所在的参考坐标系已经被初始化
 *
 */
SG::DataStructure::FEM::CoordStatus CylinderCoord::QueryStatus (ICoordinatePArray& coordSet) const
{
    if (Status_Initialized == m_status)
        return Status_Initialized;

    auto fundA = (m_ref[0] == 0) || (coordSet[m_ref[0]]->QueryStatus (coordSet) == Status_Initialized);
    if (!fundA)
        return Status_NeedOther;

    auto fundB = (m_ref[1] == 0) || (coordSet[m_ref[1]]->QueryStatus (coordSet) == Status_Initialized);
    if (!fundB)
        return Status_NeedOther;

    auto fundC = (m_ref[2] == 0) || (coordSet[m_ref[2]]->QueryStatus (coordSet) == Status_Initialized);
    if (!fundC)
        return Status_NeedOther;

    return Status_Ready;
}

void CylinderCoord::SetRefCoordId (std::size_t index, SG::DataStructure::Common::Id refId)
{
    assert (index < 3);
    m_ref[index] = refId;
}

/** @brief 获得定义坐标系的参考点Id*/
void CylinderCoord::GetRefPoint (_OUT SG::DataStructure::Common::Id& GA,
                                 _OUT SG::DataStructure::Common::Id& GB,
                                 _OUT SG::DataStructure::Common::Id& GC) const
{
    GA = m_G1;
    GB = m_G2;
    GC = m_G3;
}

// void CylinderCoord::GetRefPoint (_OUT Id& ref, _OUT Point& PA, Point& PB, Point& PC)
// {
//     assert (0);
// }

void CylinderCoord::GetRefPoint (_OUT SG::DataStructure::Common::Id& ref,
                                 _OUT SG::Algebra::Point& PA,
                                 _OUT SG::Algebra::Point& PB,
                                 _OUT SG::Algebra::Point& PC)
{}

Point CylinderCoord::Trans2Basic (const Real& r, const Real& theta, const Real& z) const
{
    assert (Status_Initialized == m_status);

    const auto thetaRad = PI * theta / 180;
    Real       xCP      = r * cos (thetaRad);
    Real       yCP      = r * sin (thetaRad);
    Real       zCP      = z;

    Vector3D vectorBCO = m_bases[0] * xCP + m_bases[1] * yCP + m_bases[2] * zCP;

    return Point{ m_origin.m_x + vectorBCO.m_x, m_origin.m_y + vectorBCO.m_y, m_origin.m_z + vectorBCO.m_z };
}

CylinderCoord::CylinderCoord ()
    : ICoordinate (SG::DataStructure::Common::DEFAULT_ID, SG::DataStructure::FEM::CoordTypes::COORDTYPE_Cylinder)
{}

CylinderCoord::CylinderCoord (SG::DataStructure::Common::Id id,
                              SG::DataStructure::Common::Id GA,
                              SG::DataStructure::Common::Id GB,
                              SG::DataStructure::Common::Id GC)
    : ICoordinate (id, SG::DataStructure::FEM::CoordTypes::COORDTYPE_Cylinder), m_G1 (GA), m_G2 (GB), m_G3 (GC)
{
    m_ref[0] = 0;
    m_ref[1] = 0;
    m_ref[2] = 0;
}

CylinderCoord SG::DataStructure::FEM::CORD1CData::GetCylinderCoord ()
{
    return CylinderCoord (m_id, m_g1, m_g2, m_g3);
}

/// @brief 判断两个CORD1CData是否相等
bool SG::DataStructure::FEM::operator== (const CORD1CData& a, const CORD1CData& b)
{
    if (a.m_id != b.m_id)
        return false;
    if (a.m_g1 != b.m_g1)
        return false;
    if (a.m_g2 != b.m_g2)
        return false;
    if (a.m_g3 != b.m_g3)
        return false;
    if (a.m_dominId != b.m_dominId)
        return false;

    return true;
}